import os # 导入 os 模块，用于操作系统相关功能
from typing import List # 从 typing 模块导入 List 类型提示
from langchain.document_loaders import TextLoader # 从 langchain.document_loaders 导入 TextLoader，用于加载文本文件
from langchain.text_splitter import RecursiveCharacterTextSplitter # 从 langchain.text_splitter 导入 RecursiveCharacterTextSplitter，用于递归地分割文本
from langchain.embeddings import DashScopeEmbeddings # 从 langchain.embeddings 导入 DashScopeEmbeddings，用于创建DashScope的文本嵌入向量
from langchain.vectorstores import FAISS # 从 langchain.vectorstores 导入 FAISS，用于高效相似性搜索和密集向量聚类

from dotenv import load_dotenv # 从 dotenv 模块导入 load_dotenv 函数，用于加载 .env 文件中的环境变量

load_dotenv() # 调用 load_dotenv 函数加载环境变量

# 初始化全局向量数据库变量，初始值为 None
# 这个向量数据库将用于存储文档的嵌入向量，以便进行相似性搜索
# 在实际应用中，可以考虑使用持久化存储方案，而不是内存中的全局变量
vector_store = None


def load_and_embed_documents(file_paths: List[str]):
    """
    加载指定路径的文档文件，进行文本分割，生成嵌入向量，并存储到全局向量数据库中。

    Args:
        file_paths: 包含要加载的文档文件路径的字符串列表。

    Returns:
        一个字符串，表示成功载入的文档段落数量。
    """
    global vector_store # 声明使用全局变量 vector_store

    all_docs = [] # 初始化一个空列表，用于存储从所有文件中加载的文档
    # 遍历传入的文件路径列表
    for path in file_paths:
        # 使用 TextLoader 加载指定路径的文本文件，指定编码为 utf-8
        loader = TextLoader(path, encoding='utf-8')
        # 加载文档内容
        documents = loader.load()
        # 将加载的文档添加到 all_docs 列表中
        all_docs.extend(documents)

    # 初始化文本分割器
    # RecursiveCharacterTextSplitter 会尝试多种分隔符进行递归分割，直到满足块大小要求
    text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=500, # 设置每个文本块的最大字符数
        chunk_overlap=50 # 设置相邻文本块之间的重叠字符数，有助于保留上下文
    )
    # 使用文本分割器分割加载的文档
    docs = text_splitter.split_documents(all_docs)

    # 初始化嵌入模型
    embeddings = DashScopeEmbeddings() # 使用 DashScope 的文本嵌入模型
    # 从分割后的文档和嵌入模型创建 FAISS 向量存储
    # FAISS 会为每个文档块生成嵌入向量并构建索引
    vector_store = FAISS.from_documents(docs, embeddings)
    # 返回载入的文档段落数量
    return f"共载入文档段落数: {len(docs)}"


def retrieve_relevant_docs(query: str, k: int = 4):
    """
    在全局向量数据库中检索与查询最相似的文档段落。

    Args:
        query: 用户输入的查询字符串。
        k: 要检索的最相似文档段落的数量，默认为 4。

    Returns:
        一个包含与查询最相似的文档段落的列表。如果向量数据库未初始化，则返回空列表。
    """
    # 检查向量数据库是否已初始化
    if vector_store is None:
        # 如果未初始化，返回空列表
        return []
    # 使用向量数据库执行相似性搜索，找到与查询最相似的 k 个文档段落
    return vector_store.similarity_search(query, k=k)
